<!DOCTYPE html>
<html>
<head>
<title>Convex Lens Imaging</title>
</head>
<body>
<canvas id="physicsCanvas" width="650" height="350"></canvas>
<script>
const canvas = document.getElementById('physicsCanvas');
const ctx = canvas.getContext('2d');

// --- Style ---
ctx.strokeStyle = 'black';
ctx.fillStyle = 'black';
ctx.lineWidth = 2;
ctx.font = 'bold 16px sans-serif';

// --- Helper function to draw an arrow line and head ---
function drawArrow(ctx, fromx, fromy, tox, toy) {
    const headlen = 8;
    const dx = tox - fromx;
    const dy = toy - fromy;
    const angle = Math.atan2(dy, dx);
    
    ctx.beginPath();
    ctx.moveTo(fromx, fromy);
    ctx.lineTo(tox, toy);
    ctx.stroke();

    ctx.beginPath();
    ctx.moveTo(tox, toy);
    ctx.lineTo(tox - headlen * Math.cos(angle - Math.PI / 6), toy - headlen * Math.sin(angle - Math.PI / 6));
    ctx.lineTo(tox - headlen * Math.cos(angle + Math.PI / 6), toy - headlen * Math.sin(angle + Math.PI / 6));
    ctx.closePath();
    ctx.fill();
}

// --- Parameters and Coordinates ---
const scale = 100; // 100 pixels = 1 unit (F=1)
const cy = 175; // y-coordinate of the principal axis
const lens_x = 220; // x-coordinate of the lens center

// Object properties from problem
const u = -1.5;
const f = 1.0;
const arrow_len_obj = 0.5;

// Calculated image properties
const v = 3.0;
const m_t = -2.0;

// Convert units to pixels
const F_px = f * scale;
const O_x = lens_x + u * scale; // 220 - 150 = 70
const O_prime_x = lens_x + v * scale; // 220 + 300 = 520
const arrow_len_obj_px = arrow_len_obj * scale; // 50
const arrow_len_img_trans_px = Math.abs(m_t) * arrow_len_obj_px; // 100
const arrow_len_img_long_px = 1.0 * scale; // 100 (from calculation |v2-v1|=1)

// --- Drawing ---

// 1. Principal Axis
drawArrow(ctx, 20, cy, 630, cy);
ctx.font = 'italic bold 18px Times New Roman';
ctx.fillText("C'", 630, cy - 10);
ctx.font = 'bold 16px sans-serif';


// 2. Convex Lens
ctx.beginPath();
const lens_h = 80;
ctx.moveTo(lens_x, cy - lens_h);
ctx.quadraticCurveTo(lens_x + 30, cy, lens_x, cy + lens_h);
ctx.quadraticCurveTo(lens_x - 30, cy, lens_x, cy - lens_h);
ctx.stroke();

// 3. Focal Points
const F1_x = lens_x - F_px;
const F2_x = lens_x + F_px;
ctx.beginPath();
ctx.arc(F1_x, cy, 3, 0, 2 * Math.PI);
ctx.fill();
ctx.font = 'bold 18px Times New Roman';
ctx.fillText('F', F1_x - 5, cy + 25);

ctx.beginPath();
ctx.arc(F2_x, cy, 3, 0, 2 * Math.PI);
ctx.fill();
ctx.fillText('F', F2_x - 5, cy + 25);
ctx.font = 'bold 16px sans-serif';


// 4. Object
// Point O
ctx.beginPath();
ctx.arc(O_x, cy, 3, 0, 2 * Math.PI);
ctx.fill();
ctx.font = 'bold 18px Times New Roman';
ctx.fillText('O', O_x - 5, cy + 25);

// Arrow b (up)
const b_tip_y = cy - arrow_len_obj_px;
drawArrow(ctx, O_x, cy, O_x, b_tip_y);
ctx.font = 'italic bold 18px Times New Roman';
ctx.fillText('b', O_x + 10, b_tip_y + 10);

// Arrow a (out of page -> left-down)
const a_dx = -arrow_len_obj_px * Math.cos(Math.PI/4);
const a_dy = arrow_len_obj_px * Math.sin(Math.PI/4);
const a_tip_x = O_x + a_dx;
const a_tip_y = cy + a_dy;
drawArrow(ctx, O_x, cy, a_tip_x, a_tip_y);
ctx.fillText('a', a_tip_x - 20, a_tip_y);

// Arrow c (along axis, away from lens -> left)
const c_tip_x = O_x - arrow_len_obj_px;
drawArrow(ctx, O_x, cy, c_tip_x, cy);
ctx.fillText('c', O_x - 20, cy - 10);


// 5. Image
// Point O'
ctx.beginPath();
ctx.arc(O_prime_x, cy, 3, 0, 2 * Math.PI);
ctx.fill();
ctx.font = 'bold 18px Times New Roman';
ctx.fillText("O'", O_prime_x - 5, cy + 25);

// Arrow b' (down, magnified)
const b_prime_tip_y = cy + arrow_len_img_trans_px;
drawArrow(ctx, O_prime_x, cy, O_prime_x, b_prime_tip_y);
ctx.font = 'italic bold 18px Times New Roman';
ctx.fillText('b', O_prime_x + 10, b_prime_tip_y - 10);

// Arrow a' (into page -> right-up, magnified)
const a_prime_dx = m_t * a_dx; // Inversion
const a_prime_dy = m_t * a_dy; // Inversion
const a_prime_tip_x = O_prime_x + a_prime_dx;
const a_prime_tip_y = cy + a_prime_dy;
drawArrow(ctx, O_prime_x, cy, a_prime_tip_x, a_prime_tip_y);
ctx.fillText('a', a_prime_tip_x, a_prime_tip_y - 10);

// Arrow c' (along axis, towards lens, magnified)
const c_prime_tip_x = O_prime_x - arrow_len_img_long_px;
drawArrow(ctx, O_prime_x, cy, c_prime_tip_x, cy);

// 6. Caption
ctx.font = 'bold 18px sans-serif';
ctx.fillText('Fig. 1.16', 280, 330);

</script>
</body>
</html>